﻿namespace com.vs.Inventory.BL
{
    using com.vs.DataAccess;
    using com.vs.DataAccess.DO;
    using com.vs.General;
    using com.vs.Receiving.BL;
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Text;

    public class LocatingHelper
    {
        private static com.vs.Inventory.BL.LocatingHelper _helper = null;
        public bool bCreateTask = true;

        private string adjustInvForLocating(Session sess, InventoryTransDS itDS)
        {
            InventoryChangeDS item = null;
            List<InventoryChangeDS> arInvChgDS = null;
            LocationManager manager = null;
            string str;
            try
            {
                arInvChgDS = new List<InventoryChangeDS>();
                item = new InventoryChangeDS {
                    WAREHOUSE = itDS.WAREHOUSE,
                    LOCATION = itDS.FROM_LOC,
                    ITEM = itDS.ITEM,
                    COMPANY = itDS.COMPANY,
                    LPN = itDS.FROM_LPN,
                    ATTRIBUTE_NUM = itDS.ATTRIBUTE_NUM,
                    QUANTITY = itDS.QUANTITY,
                    QUANTITY_UM = itDS.QUANTITY_UM,
                    INVENTORY_STS = itDS.INVENTORY_STS
                };
                if (this.bCreateTask)
                {
                    item.OP_ONHANDQTY = "";
                    item.OP_INTRANQTY = "";
                    item.OP_ALLOCQTY = "+";
                }
                else
                {
                    item.OP_ONHANDQTY = "-";
                    item.OP_INTRANQTY = "";
                    item.OP_ALLOCQTY = "";
                }
                arInvChgDS.Add(item);
                item = new InventoryChangeDS {
                    WAREHOUSE = itDS.WAREHOUSE,
                    LOCATION = itDS.TO_LOC,
                    ITEM = itDS.ITEM,
                    COMPANY = itDS.COMPANY,
                    ATTRIBUTE_NUM = itDS.ATTRIBUTE_NUM,
                    QUANTITY = itDS.QUANTITY,
                    QUANTITY_UM = itDS.QUANTITY_UM,
                    INVENTORY_STS = itDS.INVENTORY_STS
                };
                manager = new LocationManager();
                if (LocationManager.DoseLocTrackLPN(sess, itDS.WAREHOUSE, itDS.TO_LOC))
                {
                    item.LPN = itDS.TO_LPN;
                }
                if (this.bCreateTask)
                {
                    item.OP_ONHANDQTY = "";
                    item.OP_INTRANQTY = "+";
                    item.OP_ALLOCQTY = "";
                }
                else
                {
                    item.OP_ONHANDQTY = "+";
                    item.OP_INTRANQTY = "";
                    item.OP_ALLOCQTY = "";
                }
                arInvChgDS.Add(item);
                str = new com.vs.Inventory.BL.InventoryHelper().AdjustInventory(sess, arInvChgDS);
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                str = MessageManager.MSG_GEN_000;
            }
            finally
            {
                item = null;
                arInvChgDS = null;
            }
            return str;
        }

        private List<string> getDefaultLocatingRule(Session sess)
        {
            return new List<string> { "SELECT LOCATION FROM LOCATION WHERE LOCATION_STS = 'Empty'" };
        }

        public static com.vs.Inventory.BL.LocatingHelper GetInstance()
        {
            if (_helper == null)
            {
                _helper = new com.vs.Inventory.BL.LocatingHelper();
            }
            return _helper;
        }

        public List<InventoryTransDS> LocateItem(Session sess, InventoryDS ivDS, string stLocRule, string stPutLoc, ref string stError)
        {
            List<InventoryTransDS> list = null;
            try
            {
                if (StringManager.IsEmpty(stPutLoc))
                {
                    list = this.locateItemByRule(sess, ivDS, stLocRule, ref stError);
                }
                else
                {
                    list = this.locateItemWithLoc(sess, ivDS, stPutLoc, ref stError);
                }
                if (!StringManager.IsEmpty(stError))
                {
                    return null;
                }
                return list;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                stError = MessageManager.MSG_GEN_000;
                return null;
            }
        }

        private List<InventoryTransDS> locateItemByRule(Session sess, InventoryDS ivDS, string stRule, ref string stError)
        {
            Dictionary<string, int> dictionary = null;
            Dictionary<string, KeyValuePair<string, object>> dcCond = null;
            List<LocatingRuleDetailDO> list = null;
            List<InventoryTransDS> list2 = null;
            List<InventoryTransDS> list3 = null;
            try
            {
                list2 = new List<InventoryTransDS>();
                dictionary = ItemManager.BreakItemQtyIntoUMs(sess, ivDS.COMPANY, ivDS.ITEM, ivDS.QUANTITY);
                foreach (KeyValuePair<string, int> pair in dictionary)
                {
                    if (pair.Value > 0)
                    {
                        ivDS.QUANTITY = pair.Value;
                        dcCond = new Dictionary<string, KeyValuePair<string, object>>();
                        dcCond.Add("LOCATING_RULE", new KeyValuePair<string, object>("=", stRule));
                        dcCond.Add("QUANTITY_UM", new KeyValuePair<string, object>("=", pair.Key));
                        list = LocatingRuleDetailDO.GetListByColumns(sess, DictionaryManager.ToList(dcCond), null);
                        if ((list == null) || (list.Count < 1))
                        {
                            stError = MessageManager.MSG_INV_008;
                            return null;
                        }
                        foreach (LocatingRuleDetailDO ldo in list)
                        {
                            if (ivDS.QUANTITY <= 0)
                            {
                                break;
                            }
                            list3 = this.locateItemToLocations(sess, ivDS, pair.Key, ldo.LOC_SEL_ID, ldo.SPLIT_QTY == "Y", ref stError);
                            if (!StringManager.IsEmpty(stError))
                            {
                                HistoryManager.SaveProcessHistory(sess, HistoryManager.ProcessType.iLocate, HistoryManager.Condition.iFailed, stError, stRule, ivDS.ITEM, ivDS.COMPANY, ivDS.QUANTITY);
                            }
                            else
                            {
                                foreach (InventoryTransDS sds in list3)
                                {
                                    list2.Add(sds);
                                }
                            }
                        }
                    }
                }
                return list2;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                stError = MessageManager.MSG_GEN_000;
                return null;
            }
        }

        private InventoryTransDS locateItemToLocation(Session sess, InventoryDS ivDS, string stLoc, string stProcUM, bool bSplitQty, ref string stError)
        {
            DataHelper helper = null;
            DataTable table = null;
            string cmdText = null;
            InventoryTransDS sds2;
            int @int = 0;
            int num2 = 0;
            int qUANTITY = 0;
            int num4 = 0;
            int num5 = 0;
            InventoryTransDS itDS = null;
            try
            {
                helper = new DataHelper(sess);
                cmdText = " SELECT SUM(ON_HAND_QTY + IN_TRANSIT_QTY) FROM LOCATION_INVENTORY  WHERE WAREHOUSE = @Warehouse      AND COMPANY = @Company      AND ITEM = @Item      AND LOCATION = @Location  GROUP BY WAREHOUSE, COMPANY, ITEM, LOCATION ";
                table = helper.GetTable(CommandType.Text, cmdText, new IDataParameter[] { DataHelper.BuildParameter(sess, "@Warehouse", ivDS.WAREHOUSE), DataHelper.BuildParameter(sess, "@Company", ivDS.COMPANY), DataHelper.BuildParameter(sess, "@Item", ivDS.ITEM), DataHelper.BuildParameter(sess, "@Location", stLoc) });
                if (!DataManager.IsEmpty(table))
                {
                    @int = DataManager.GetInt(table.Rows[0], 0);
                }
                num2 = new com.vs.Inventory.BL.InventoryHelper().GetLocCapacity(sess, ivDS.WAREHOUSE, ivDS.COMPANY, ivDS.ITEM, stLoc);
                if (num2 < 1)
                {
                    stError = MessageManager.MSG_INV_005;
                    return null;
                }
                num4 = num2 - @int;
                if (num4 <= 0)
                {
                    return null;
                }
                num5 = ItemManager.GetConversionQty(sess, ivDS.ITEM, ivDS.COMPANY, stProcUM);
                if (num5 < 1)
                {
                    stError = MessageManager.MSG_ITM_001;
                    return null;
                }
                num4 = (num4 / num5) * num5;
                if (num4 >= ivDS.QUANTITY)
                {
                    qUANTITY = ivDS.QUANTITY;
                }
                else
                {
                    if (!bSplitQty)
                    {
                        stError = MessageManager.MSG_INV_012;
                        return null;
                    }
                    qUANTITY = num4;
                }
                ivDS.QUANTITY -= qUANTITY;
                itDS = new InventoryTransDS {
                    WAREHOUSE = ivDS.WAREHOUSE,
                    COMPANY = ivDS.COMPANY,
                    ITEM = ivDS.ITEM,
                    ATTRIBUTE_NUM = ivDS.ATTRIBUTE_NUM,
                    FROM_LOC = ivDS.LOCATION,
                    FROM_LPN = ivDS.LPN,
                    TO_LOC = stLoc,
                    TO_LPN = ivDS.LPN,
                    INVENTORY_STS = ivDS.INVENTORY_STS,
                    QUANTITY = qUANTITY,
                    QUANTITY_UM = ivDS.QUANTITY_UM
                };
                stError = this.adjustInvForLocating(sess, itDS);
                if (!StringManager.IsEmpty(stError))
                {
                    HistoryManager.SaveProcessHistory(sess, HistoryManager.ProcessType.iLocate, HistoryManager.Condition.iError, stError, itDS.ITEM, itDS.COMPANY, itDS.TO_LOC, itDS.QUANTITY);
                    ivDS.QUANTITY += qUANTITY;
                    return null;
                }
                sds2 = itDS;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                stError = MessageManager.MSG_GEN_000;
                sds2 = null;
            }
            finally
            {
                if (helper != null)
                {
                    helper.Dispose();
                }
            }
            return sds2;
        }

        private List<InventoryTransDS> locateItemToLocations(Session sess, InventoryDS ivDS, string stProcUM, int iLocSelID, bool bSplitQty, ref string stError)
        {
            List<InventoryTransDS> list = null;
            DataHelper helper = null;
            DataTable table = null;
            InventoryTransDS item = null;
            FilterConfigDetailDO modelByPK = null;
            string stLoc = null;
            List<InventoryTransDS> list2;
            try
            {
                modelByPK = FilterConfigDetailDO.GetModelByPK(sess, iLocSelID);
                if (modelByPK == null)
                {
                    stError = MessageManager.MSG_LOC_002;
                    return null;
                }
                helper = new DataHelper(sess);
                table = helper.GetTable(CommandType.Text, modelByPK.FILTER_STATEMENT, new IDataParameter[] { DataHelper.BuildParameter(sess, "@COMPANY", ivDS.COMPANY), DataHelper.BuildParameter(sess, "@ITEM", ivDS.ITEM) });
                if (DataManager.IsEmpty(table))
                {
                    stError = MessageManager.MSG_INV_006;
                    return null;
                }
                list = new List<InventoryTransDS>();
                foreach (DataRow row in table.Rows)
                {
                    if (ivDS.QUANTITY <= 0)
                    {
                        break;
                    }
                    stLoc = DataManager.GetString(row, "LOCATION");
                    item = this.locateItemToLocation(sess, ivDS, stLoc, stProcUM, bSplitQty, ref stError);
                    if (!StringManager.Equals(stError, MessageManager.MSG_INV_012))
                    {
                        HistoryManager.SaveProcessHistory(sess, HistoryManager.ProcessType.iLocate, HistoryManager.Condition.iFailed, stError, ivDS.ITEM, ivDS.QUANTITY, stLoc, null);
                    }
                    if ((item != null) && (item.QUANTITY > 0))
                    {
                        list.Add(item);
                    }
                }
                list2 = list;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                stError = MessageManager.MSG_GEN_000 + exception.Message;
                list2 = null;
            }
            finally
            {
                if (helper != null)
                {
                    helper.Dispose();
                }
            }
            return list2;
        }

        public List<InventoryTransDS> locateItemWithLoc(Session sess, InventoryDS ivDS, string stLoc, ref string stError)
        {
            InventoryTransDS itDS = null;
            try
            {
                itDS = new InventoryTransDS {
                    WAREHOUSE = ivDS.WAREHOUSE,
                    COMPANY = ivDS.COMPANY,
                    ITEM = ivDS.ITEM,
                    ATTRIBUTE_NUM = ivDS.ATTRIBUTE_NUM,
                    FROM_LOC = ivDS.LOCATION,
                    FROM_LPN = ivDS.LPN,
                    TO_LOC = stLoc,
                    QUANTITY = ivDS.QUANTITY,
                    QUANTITY_UM = ivDS.QUANTITY_UM,
                    INVENTORY_STS = ivDS.INVENTORY_STS
                };
                stError = this.adjustInvForLocating(sess, itDS);
                if (!StringManager.IsEmpty(stError))
                {
                    return null;
                }
                return new List<InventoryTransDS> { itDS };
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                stError = MessageManager.MSG_GEN_000 + exception.Message;
                return null;
            }
        }

        public List<InventoryTransDS> LocateReceiptContainer(Session sess, ReceiptContainerDO rcDO, int iWaveNum, ref string stError)
        {
            InventoryDS ivDS = null;
            List<InventoryTransDS> list = null;
            ReceiptContainerDO rdo = null;
            int num = 0;
            Dictionary<string, object> dcData = null;
            StringBuilder builder = null;
            bool flag = false;
            try
            {
                ivDS = new InventoryDS {
                    ATTRIBUTE_NUM = rcDO.ATTRIBUTE_NUM,
                    ATTRIBUTE1 = rcDO.ATTRIBUTE1,
                    ATTRIBUTE2 = rcDO.ATTRIBUTE2,
                    ATTRIBUTE3 = rcDO.ATTRIBUTE3,
                    ATTRIBUTE4 = rcDO.ATTRIBUTE4,
                    ATTRIBUTE5 = rcDO.ATTRIBUTE5,
                    ATTRIBUTE6 = rcDO.ATTRIBUTE6,
                    ATTRIBUTE7 = rcDO.ATTRIBUTE7,
                    ATTRIBUTE8 = rcDO.ATTRIBUTE8,
                    COMPANY = rcDO.COMPANY,
                    LOCATION = rcDO.FROM_LOCATION,
                    INVENTORY_STS = rcDO.INVENTORY_STS,
                    ITEM = rcDO.ITEM,
                    LPN = rcDO.CONTAINER_ID,
                    QUANTITY = rcDO.QUANTITY,
                    QUANTITY_UM = rcDO.QUANTITY_UM,
                    WAREHOUSE = rcDO.WAREHOUSE
                };
                if (StringManager.IsEmpty(rcDO.TO_LOCATION))
                {
                    list = this.locateItemByRule(sess, ivDS, rcDO.LOCATING_RULE, ref stError);
                }
                else
                {
                    list = this.locateItemWithLoc(sess, ivDS, rcDO.TO_LOCATION, ref stError);
                }
                if (!StringManager.IsEmpty(stError))
                {
                    return null;
                }
                builder = new StringBuilder();
                flag = list.Count > 1;
                if (!flag)
                {
                    flag = new ReceiptContManager().IsParentContainer(sess, rcDO.INTERNAL_CONTAINER_NUM);
                }
                foreach (InventoryTransDS sds in list)
                {
                    if (flag)
                    {
                        rdo = rcDO.Copy(sess);
                        rdo.QUANTITY = sds.QUANTITY;
                        rdo.QUANTITY_UM = sds.QUANTITY_UM;
                        rdo.TO_LOCATION = sds.TO_LOC;
                        string msg = rdo.Insert(sess);
                        if (!StringManager.IsErrorMessage(msg))
                        {
                            num = Convert.ToInt32(msg);
                            rdo.INTERNAL_CONTAINER_NUM = num;
                        }
                        else
                        {
                            builder.AppendLine(msg);
                            continue;
                        }
                        if ((rcDO.QUANTITY - sds.QUANTITY) > 0)
                        {
                            rcDO.QUANTITY -= sds.QUANTITY;
                            dcData = new Dictionary<string, object>();
                            dcData.Add("QUANTITY", rcDO.QUANTITY);
                            rcDO.Update(sess, dcData);
                        }
                        else
                        {
                            rcDO.Delete(sess);
                        }
                    }
                    else
                    {
                        dcData = new Dictionary<string, object>();
                        dcData.Add("TO_LOCATION", sds.TO_LOC);
                        rcDO.Update(sess, dcData);
                        rdo = rcDO;
                        rdo.TO_LOCATION = sds.TO_LOC;
                    }
                    new ReceiptLocateRequestDO { 
                        ATTRIBUTE_NUM = rdo.ATTRIBUTE_NUM, COMPANY = rdo.COMPANY, CONTAINER_ID = rdo.CONTAINER_ID, DATE_TIME_STAMP = DateTime.Now, FROM_LOC = rdo.FROM_LOCATION, INTERNAL_CONTAINER_NUM = rdo.INTERNAL_CONTAINER_NUM, INTERNAL_RECEIPT_LINE_NUM = rdo.INTERNAL_RECEIPT_LINE_NUM, INTERNAL_RECEIPT_NUM = rdo.INTERNAL_RECEIPT_NUM, ITEM = rdo.ITEM, ITEM_DESC = rdo.ITEM_DESC, LOCATE_QTY = sds.QUANTITY, PARENT_CONTAINER_ID = rcDO.CONTAINER_ID, PARENT_CONTAINER_NUM = rcDO.INTERNAL_CONTAINER_NUM, QUANTITY_UM = sds.QUANTITY_UM, RECEIPT_DATE = DateTime.Now, RECEIPT_ID = rdo.RECEIPT_ID, 
                        RECEIPT_TYPE = rdo.RECEIPT_TYPE, TASK_CREATED = "N", TO_LOC = sds.TO_LOC, USER_STAMP = sess.User, WAREHOUSE = rdo.WAREHOUSE, INTERNAL_WAVE_NUM = iWaveNum
                     }.Insert(sess);
                }
                return list;
            }
            catch (Exception exception)
            {
                ExceptionManager.LogException(sess, exception);
                stError = MessageManager.MSG_GEN_000;
                return null;
            }
        }
    }
}

